{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python 正则表达式\n",
    "# 1、re.match函数\n",
    "re.match 尝试从字符串的起始位置匹配一个模式，如果不是起始位置匹配成功的话，match()就返回none。\n",
    "函数语法：\n",
    "re.match(pattern, string, flags=0)\n",
    "函数参数说明：\n",
    "参数\t描述\n",
    "pattern\t匹配的正则表达式\n",
    "string\t要匹配的字符串。\n",
    "flags\t标志位，用于控制正则表达式的匹配方式，如：是否区分大小写，多行匹配等等。参见：正则表达式修饰符 - 可选标志\n",
    "\n",
    "匹配成功re.match方法返回一个匹配的对象，否则返回None。\n",
    "我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。\n",
    "匹配对象方法\t描述\n",
    "group(num=0)\t匹配的整个表达式的字符串，group() 可以一次输入多个组号，在这种情况下它将返回一个包含那些组所对应值的元组。\n",
    "groups()\t返回一个包含所有小组字符串的元组，从 1 到 所含的小组号。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 3)\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# span()函数表示匹配的范围包前不包后\n",
    "# 返回匹配的位置\n",
    "print(re.match('www','www.runoob.com').span())  # 在起始位置匹配\n",
    "print(re.match('com','www.runoob.com'))  # 不在起始位置匹配返回None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在正则表达式中用小括号括起来就可以获取想要的匹配目标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "26\n",
      "matchObj.group() :  Cats are smarter than dogs (0, 26)\n",
      "matchObj.group(1) :  Cats (0, 26)\n",
      "matchObj.group(2) :  smarter\n",
      "matchObj.groups(): ('Cats', 'smarter')\n"
     ]
    }
   ],
   "source": [
    "# 如果正则表达式出现小括号，那么第一个小括号就是group(1),第二个小括号就是group(2),\n",
    "# groups()返回所有的小括号匹配的字符串，返回一个元组类型的数据\n",
    "# 使用group方法提取到匹配的内容\n",
    "import re\n",
    " \n",
    "line = \"Cats are smarter than dogs\"\n",
    "print(len(line))\n",
    "matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)\n",
    " \n",
    "if matchObj:\n",
    "    print('matchObj.group() : ', matchObj.group(),matchObj.span())\n",
    "    print(\"matchObj.group(1) : \", matchObj.group(1),matchObj.span())\n",
    "    print(\"matchObj.group(2) : \", matchObj.group(2))\n",
    "    print('matchObj.groups():',matchObj.groups())\n",
    "else:\n",
    "    print(\"No match!!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2、re.search进行正则字符串匹配的方法，匹配的是整个字符串,（只要有一个匹配成功就不往下找）!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(10, 13), match='com'>\n",
      "(10, 13)\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "print(re.search('com','www.baidu.com'))\n",
    "print(re.search('com','www.baidu.com').span())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10, 13)\n",
      "com\n"
     ]
    }
   ],
   "source": [
    "# 使用group方法提取到匹配的内容\n",
    "import re\n",
    "result = re.search('com','www.baidu.com')\n",
    "print(result.span())\n",
    "print(result.group())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[]表示一个匹配范围，一个方括号只匹配其中的一个值而已\n",
    "print(re.findall('[asd]',s))  # ['d', 'a', 's', 'd', 'd', 'a', 'a', 's', 'd']\n",
    "如[0-9]表示匹配数字\n",
    "如果出现多个[][]表示紧挨着为一个整体进行匹配"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(2, 4), match='3a'>\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "s = '哈哈3a'\n",
    "\n",
    "result1 = re.search('[0-9][a-z]',s)\n",
    "print(result1)\n",
    "# 如果出现多个[][]表示紧挨着为一个整体进行匹配\n",
    "s2 = '哈哈33'\n",
    "result2 = re.search('[0-9][a-z]',s2)\n",
    "print(result2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "g1f\n",
      "()\n"
     ]
    }
   ],
   "source": [
    "# re.search只要有一个匹配成功就不往下找\n",
    "import re\n",
    "\n",
    "s = 'dgfasdjfg1fdaasf4gdfg8987874'\n",
    "result = re.search('[a-z][0-9][a-z]',s)\n",
    "print(result.group())  # 返回值g1f\n",
    "print(result.groups())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3、re.findall匹配整个字符串，查找所有符合正则表达式的字符串，返回一个列表的形式.如果没有找到匹配的，则返回空列表。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['d', 'a', 's', 'd', 'd', 'a', 'a', 's', 'd']\n",
      "['g1f', 'f4g']\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "s = 'dgfasdjfg1fdaasf4gdfg8987874'\n",
    "print(re.findall('[asd]',s))  # ['d', 'a', 's', 'd', 'd', 'a', 'a', 's', 'd']\n",
    "result = re.findall('[a-z][0-9][a-z]',s)\n",
    "print(result)  # ['g1f', 'f4g']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 符号： +  匹配前面的字符依次到多次\n",
    "# *  ？   {m}  {,n}  {m,n}  {m,}  ^  $"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a7a', 'a88a', 'a7878a']\n"
     ]
    }
   ],
   "source": [
    "# 查找所有符合以下格式的一个为字母中间为1-n个数字最后一个为字母的字符串\n",
    "import re\n",
    "\n",
    "msg = 'a7afdghfjka88ahfujgma7878a'\n",
    "result = re.findall('[a-z][0-9]+[a-z]',msg)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 10), match='1149691900'>\n"
     ]
    }
   ],
   "source": [
    "# qq号码的验证5~11为开头不能是0\n",
    "\n",
    "import re\n",
    "qq = '1149691900'\n",
    "\n",
    "result = re.match('[1-9][0-9]{4,10}',qq)  # 如果不符合会报错\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 8), match='admin001'>\n",
      "<_sre.SRE_Match object; span=(0, 8), match='admin001'>\n",
      "加^$限定匹配整个字符串的结果\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 用户名可以是字母或者数字，不能是数字开头，用户名的长度必须是6位以上[0-9a-zA-Z]\n",
    "# 使用^和$去匹配整个字符串\n",
    "import re\n",
    "\n",
    "username = 'admin001'\n",
    "username1 = 'admin001##$%$'\n",
    "s = '[a-zA-Z][0-9a-zA-Z]{5,}'\n",
    "s1 = '[a-zA-Z][0-9a-zA-Z]{5,}$'\n",
    "result = re.match(s,username)\n",
    "print(result)\n",
    "result1 = re.match(s,username1)  # 这样子就会匹配的不是想要限制的结果\n",
    "print(result1)\n",
    "print('加^$限定匹配整个字符串的结果')\n",
    "result2 = re.match(s1,username1)  # admin001##$%$  这个username就是不符合用户名的定义\n",
    "print(result2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 8), match='_dfsa002'>\n"
     ]
    }
   ],
   "source": [
    "# 用户名可以是字母或者数字下划线，不能是数字开头，用户名的长度必须是6位以上[0-9a-zA-Z_] -->\\w代替\n",
    "import re\n",
    "\n",
    "username = '_dfsa002'\n",
    "s = '[a-zA-Z_]\\w{5,}$'\n",
    "result = re.match(s,username)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['bb.py', 'uu.py']\n"
     ]
    }
   ],
   "source": [
    "# 匹配以.py结尾的文件  \\b表示边界字符\n",
    "import re\n",
    "msg = 'a*bpy  ab.txt bb.py  kk.png uu.py apyb.txt'\n",
    "\n",
    "s = r'\\w*\\.py\\b'  # \\.进行转义\n",
    "result = re.findall(s,msg)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 分组  符号 '|'\n",
    "# ()表示一个整体"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 1), match='0'>\n"
     ]
    }
   ],
   "source": [
    "# 匹配0-100的数字\n",
    "import re\n",
    "\n",
    "n = '100'\n",
    "\n",
    "result = re.match(r'[1-9]?\\d?$|100$',n)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 17), match='1149691900@qq.com'>\n"
     ]
    }
   ],
   "source": [
    "# 邮箱验证\n",
    "# [\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?\n",
    "\n",
    "import re\n",
    "mail = '1149691900@qq.com'\n",
    "s = r'^[\\w!#$%&\\'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&\\'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?$'\n",
    "result = re.match(s,mail)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13788819348\n"
     ]
    }
   ],
   "source": [
    "# 不是以7、4结尾的手机号码（11位）\n",
    "\n",
    "import re\n",
    "phone = '13788819348'\n",
    "result = re.match(r'1\\d{9}[0-35689]',phone)\n",
    "print(result.group())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 14), match='<h1>hello</h1>'>\n",
      "<h1>hello</h1>\n",
      "hello\n"
     ]
    }
   ],
   "source": [
    "# 匹配标签里面的内容\n",
    "import re\n",
    "msg = '<html>abc</html>'\n",
    "msg1 = '<h1>hello</h1>'\n",
    "result = re.match(r'<[0-9a-zA-Z]+>(.+)</[0-9a-zA-Z]+>$',msg1)\n",
    "print(result)\n",
    "# 如果result没有内容的话，调用group()就会报错\n",
    "print(result.group())  #  <html>abc</html>\n",
    "print(result.group(1))  # abc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 25), match='<html><h1>abc</h1></html>'>\n",
      "<html><h1>abc</h1></html>\n",
      "html\n",
      "<h1>abc</h1>\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 结合数字达到引用的前后匹配  \\+分组的组号表示引用第几组\n",
    "\n",
    "msg = '<html><h1>abc</h1></html>'\n",
    "msg1 = '<h1>hello</h2>'\n",
    "\n",
    "result = re.match(r'<([0-9a-zA-Z]+)>(.+)</\\1>$',msg)\n",
    "print(result)\n",
    "print(result.group())\n",
    "print(result.group(1))\n",
    "print(result.group(2))\n",
    "\n",
    "result2 = re.match(r'<([0-9a-zA-Z]+)>(.+)</\\1>$',msg1)\n",
    "print(result2)  # 前后不一致就会报错\n",
    "# print(result2.group())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<_sre.SRE_Match object; span=(0, 25), match='<html><h1>abc</h1></html>'>\n",
      "<html><h1>abc</h1></html>\n",
      "html\n",
      "h1\n",
      "abc\n"
     ]
    }
   ],
   "source": [
    "# 正确引用  每个括号分别匹配对应的标签\n",
    "# msg = '<html><h1>abc</h1></html>'\n",
    "import re\n",
    "msg = '<html><h1>abc</h1></html>'\n",
    "result = re.match(r'<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)</\\2></\\1>$',msg)\n",
    "print(result)\n",
    "print(result.group())\n",
    "print(result.group(1))\n",
    "print(result.group(2))\n",
    "print(result.group(3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<html><h1>abc</h1></html>\n",
      "html\n",
      "h1\n",
      "abc\n"
     ]
    }
   ],
   "source": [
    "# 以起名的方式引用前面的某个标签\n",
    "# 格式起名   (?P<名字>正则表达式)\n",
    "#     引用   (?P=名字)\n",
    "import re\n",
    "\n",
    "msg = '<html><h1>abc</h1></html>'\n",
    "result = re.match(r'<(?P<name1>[0-9a-zA-Z]+)><(?P<name2>[0-9a-zA-Z]+)>(.+)</(?P=name2)></(?P=name1)>$',msg)\n",
    "print(result.group())\n",
    "print(result.group(1))\n",
    "print(result.group(2))\n",
    "print(result.group(3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# re.sub(pattern,repl,string,count,flag)  字符串的替换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "java:90,python:90\n"
     ]
    }
   ],
   "source": [
    "# 参数repl为字符串进行简单的替换\n",
    "# 字符串的替换\n",
    "import re\n",
    "\n",
    "result = re.sub(r'\\d+','90','java:99,python:95')\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "java:100,python:96\n"
     ]
    }
   ],
   "source": [
    "# 参数repl为函数的时候的使用\n",
    "# 所有的数字加一\n",
    "import re\n",
    "\n",
    "# 这里定义一个函数里面的参数就是要替换的字符串的整个内容\n",
    "def func(temp):\n",
    "    # 里面可以直接用正则表达式匹配到对象返回的对象进行调用\n",
    "    num = temp.group()\n",
    "    if num.isdigit():\n",
    "        num1 = int(num) + 1\n",
    "        return str(num1)\n",
    "    else:\n",
    "        print('num is not a digit')\n",
    "        return '0'\n",
    "\n",
    "# 这边在调用函数的时候不用传递参数，他是自动去完成的\n",
    "result = re.sub(r'\\d+',func,'java:99,python:95')\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# re.split(pattern,string,maxsplit,flag)  对字符串进行切割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['java', '99', 'python', '95']\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "result = re.split(r'[,:]','java:99,python:95')\n",
    "print(result)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
